package com.lg.cms.shiro;

import com.lg.cms.entity.Permission;
import com.lg.cms.service.PermissionService;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.xml.ws.ServiceMode;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: shiro服务类
 * @Author: wuyuhang
 * @create: 2020-10-02 15:31
 */
@Service
@AllArgsConstructor
public class ShiroService {

    private final PermissionService permissionService;

    private final ShiroFilterFactoryBean shiroFilterFactoryBean;


    @PostConstruct
    public void init() {
        updatePermission();
    }

    /**
     * 初始化权限, 顺序拦截, 被拦截后中断, 满足条件会中断, 即权限不能在登录之下, 会被登录拦截走(权限本身基于登录, 所以不能再登录之下)
     * 权限设置顺序匿名(无需认证), 授权, 角色, 登录,
     * 相同url按顺序设置被匿名拦截(放行)的不会再被其他拦截
     */
    public Map<String, String> loadFilterChainDefinitions() {
        // 权限控制map.从数据库获取
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//        filterChainDefinitionMap.put("/kaptcha", "anon");
//        filterChainDefinitionMap.put("/login", "anon");
//        filterChainDefinitionMap.put("/error/**", "anon");
//        filterChainDefinitionMap.put("/static/**", "anon");
//        filterChainDefinitionMap.put("/images/**", "anon");
//        filterChainDefinitionMap.put("/js/**", "anon");
//        filterChainDefinitionMap.put("/css/**", "anon");
//        List<Permission> permissionList = permissionService.list();
//        for (Permission permission : permissionList) {
//            if (StringUtils.isNotBlank(permission.getUrl()) && StringUtils.isNotBlank(permission.getPerm())) {
//                String perm = "perms[" + permission.getPerm() + ']';
//                filterChainDefinitionMap.put(permission.getUrl(), perm);
//            }
//        }

        filterChainDefinitionMap.put("/admin/login", "anon");
        filterChainDefinitionMap.put("/admin/**", "roles[admin]"); //测试阶段仅使用后台登录验证
        return filterChainDefinitionMap;
    }

    /**
     * 重新加载权限
     */
    public void updatePermission() {
        synchronized (shiroFilterFactoryBean) {

            //创建一个抽象过滤器
            AbstractShiroFilter shiroFilter = null;
            try {
                //将过滤器工厂强转为抽象过滤器
                shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();

            } catch (Exception e) {
                throw new RuntimeException("获取过滤器异常");
            }
            //创建路径配置过滤器, 使用抽象过滤器
            PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
                    .getFilterChainResolver();
            //获取默认筛选链管理器
            DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver
                    .getFilterChainManager();

            // 清空老的权限控制
            manager.getFilterChains().clear();
            //清空权限字典
            shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
            shiroFilterFactoryBean.setFilterChainDefinitionMap(loadFilterChainDefinitions());
            // 重新构建生成
            Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
            chains.forEach((url, perm) -> manager.createChain(url, StringUtils.deleteWhitespace(perm)));
        }
    }
}
